package com.gdut.huayan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gdut.huayan.dao.ActivityMapper;
import com.gdut.huayan.dao.LimitNameMapper;
import com.gdut.huayan.dao.StockMapper;
import com.gdut.huayan.entity.dto.PageQuery;
import com.gdut.huayan.entity.po.Activity;
import com.gdut.huayan.entity.po.LimitName;
import com.gdut.huayan.entity.po.Stock;
import com.gdut.huayan.entity.vo.ActivityVo;
import com.gdut.huayan.service.ActivityService;
import com.gdut.huayan.service.exception.BaseException;
import com.gdut.huayan.utils.PageInfoUtils;
import com.gdut.huayan.utils.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements ActivityService {

    @Autowired
    private StockMapper stockMapper;

    @Autowired
    private LimitNameMapper limitNameMapper;

    @Override
    public PageInfo<ActivityVo> getPage(PageQuery pageQuery,Integer isSuiXi) {
        PageHelper.startPage(pageQuery.getPage(), pageQuery.getSize());
        QueryWrapper<Activity> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(pageQuery.getSearch())) {
            wrapper.like("title", "%" + pageQuery.getSearch() + "%");
        }
        if(isSuiXi != null){
            wrapper.eq("is_sui_xi",isSuiXi);
        }
        if ("ASC".equals(pageQuery.getOrder())) {
            wrapper.orderByAsc(pageQuery.getOrderKey().split(";"));
        }
        if ("DESC".equals(pageQuery.getOrder())) {
            wrapper.orderByDesc(pageQuery.getOrderKey().split(";"));
        }
        PageInfo<Activity> activities = new PageInfo<>(baseMapper.selectList(wrapper));
        if(activities.getList().size() == 0){
            return null;
        }
        List<Long> findLimitName = new ArrayList<>();
        activities.getList().forEach(a -> findLimitName.add(a.getId()));
        QueryWrapper<LimitName> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("activity_id",findLimitName);
        Map<Long, List<LimitName>> hashName = limitNameMapper.selectList(queryWrapper).stream().collect(Collectors.groupingBy(LimitName::getActivityId));
        List<ActivityVo> activityVoList = new ArrayList<>();
        activities.getList().forEach(a -> {
            activityVoList.add(new ActivityVo(a, hashName.get(a.getId())));
        });
        return new PageInfoUtils<Activity, ActivityVo>().copy(activities, activityVoList);

    }

    @Override
    public List<Activity> getFestivalLocationActivity(Long festivalId, Long locationId) {
        QueryWrapper<Stock> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("activity_id");
        queryWrapper.eq("festival_id", festivalId);
        queryWrapper.eq("location_id", locationId);
        List<Stock> stocks = stockMapper.selectList(queryWrapper);
        if(stocks.size() == 0){
            return null;
        }
        List<Long> selectIds = new ArrayList<>();
        stocks.forEach(s -> selectIds.add(s.getActivityId()));
        return baseMapper.selectBatchIds(selectIds);
    }

    @Override
    @Transactional
    public void save(ActivityVo activityVo) {
        judgeNewName(activityVo.getLimitNames());
        Activity activity = activityVo.getActivity();
        activity.setIsSystem(2);
        super.save(activity);
        activityVo.getLimitNames().forEach(t -> {
            t.setActivityId(activity.getId());
            limitNameMapper.insert(t);
        });
    }

    @Transactional
    @Override
    public void addLimitName(List<LimitName> newLimitName){
        isNotCanOperation(newLimitName.get(0).getActivityId());
        List<LimitName> limitNameList = findNameByActivityId(newLimitName.get(0).getActivityId());
        limitNameList.addAll(newLimitName);
        judgeNewName(limitNameList);
        newLimitName.forEach(nln -> limitNameMapper.insert(nln));
    }

    @Transactional
    @Override
    public void deleteLimitName(Long limitNameId) {
        nameCanOperation(limitNameId);
        limitNameMapper.deleteById(limitNameId);
    }

    @Transactional
    @Override
    public void updateLimitName(List<LimitName> limitName) {
        if(isNotCanOperation(limitName.get(0).getActivityId())){
            throw new BaseException(4000,"禁止更新使用中的活动的名字限制");
        }
        List<LimitName> limitNameList = findNameByActivityId(limitName.get(0).getActivityId());
        for (int i = 0; i < limitNameList.size(); i++) {
            for(int j = 0; j < limitName.size(); j++){
                if (limitNameList.get(i).getId().equals(limitName.get(j).getId())){
                    limitNameList.get(i).setNameType(limitName.get(j).getNameType());
                    break;
                }
            }
        }
        judgeNewName(limitNameList);
        for(LimitName lName : limitName){
            limitNameMapper.updateById(lName);
        }

    }

    @Transactional
    @Override
    public boolean removeById(Serializable id) {
        if (isNotCanOperation(id)) {
            throw new BaseException(4000, "不允许删除正在使用中的活动");
        }
        QueryWrapper<LimitName> deleteQuery = new QueryWrapper<>();
        deleteQuery.eq("activity_id", id);
        limitNameMapper.delete(deleteQuery);
        baseMapper.deleteById(id);
        return true;
    }

    @Override
    public boolean updateById(Activity activity) {
        if (isNotCanOperation(activity.getId())) {
            activity.setIsSystem(null);
            activity.setCharityType(null);
            activity.setTabletType(null);
            activity.setLastType(null);
        }
        return super.updateById(activity);
    }

    private boolean isNotCanOperation(Serializable id) {
        Activity activity = baseMapper.selectById(id);
        if (activity.getIsSystem() == 1) {
            throw new BaseException(4000, "不允许操作统自带活动");
        }
        QueryWrapper<Stock> wrapper = new QueryWrapper<>();
        wrapper.eq("activity_id", id);
        int count = stockMapper.selectCount(wrapper);
        return count != 0;
    }

    private LimitName nameCanOperation(Long limitNameId) {
        LimitName limitName = limitNameMapper.selectById(limitNameId);
        if (isNotCanOperation(limitName.getActivityId())) {
            throw new BaseException(4000, "不允许更新正在使用中的活动的名字限制");
        }
        return limitName;
    }

    private void judgeNewName(List<LimitName> names) {
        if (names != null) {
            int[] judge = new int[8];
            for (LimitName name : names) {
                try {
                    if (++judge[name.getNameType() + (name.getIsCompany() == 1 ? 0 : 4) - 1] > 1) {
                        throw new BaseException(4000, "名字限制类型重复");
                    }
                } catch (ArrayIndexOutOfBoundsException e) {
                    throw new BaseException(4000, "nameType数值错误");
                }
            }
        }

    }


    private List<LimitName> findNameByActivityId(Long activityId){
        QueryWrapper<LimitName> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("activity_id", activityId);
        return limitNameMapper.selectList(queryWrapper);
    }


}
